package com.korustar.autumnal.spring;

import java.util.ArrayList;
import java.util.List;
import java.util.Properties;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.config.PropertyPlaceholderConfigurer;
import org.springframework.util.PropertyPlaceholderHelper;

/**
 * For working with Property Placeholders ...
 * 
 * @author amir
 *
 */
public class PropertyPlaceholderResolution {
	private static Logger LOGGER = LoggerFactory.getLogger( PropertyPlaceholderResolution.class );
	
	private final PropertyPlaceholderHelper placeholderHelper= new PropertyPlaceholderHelper(PropertyPlaceholderConfigurer.DEFAULT_PLACEHOLDER_PREFIX, PropertyPlaceholderConfigurer.DEFAULT_PLACEHOLDER_SUFFIX );

	private Properties properties;
	
	@SuppressWarnings("unchecked")
	public <T> T resolve(String name) {
		String replaced= this.resolveString(name);
		return (T)replaced;
	}
	
	public Integer resolveInt(String name) {
		String replaced= this.resolveString(name);
		return Integer.valueOf(replaced);
	}
	
	public String resolveString(String valToReplace) {
		if(this.properties==null) {
			LOGGER.warn("no properties with which to resolve {}",valToReplace);
			return valToReplace;
		}
		String replaced= this.placeholderHelper.replacePlaceholders(valToReplace, this.properties);
		if(!valToReplace.equals(replaced)) {
			LOGGER.info("Resolving {} to {}", valToReplace, replaced );
		}
		return replaced;
	}
	

	private final String placeholderPrefixRegex="\\$\\{";
	private final String placeholderSuffixRegex="\\}";
	public List<Object> serialize(String strVal) {

		List<Object> parts= new ArrayList<Object>();
		String[] split = strVal.split(this.placeholderPrefixRegex);
		boolean first=true;
		for(String item : split) {
			if(first==true) {
				parts.add(item);
				first=false;
			} else {
				String[] split2 = item.split(this.placeholderSuffixRegex);
				//parts.add()
				parts.add(new Property(split2[0]));
				if(split2.length>1) {
					parts.add(split2[1]);
				}
			}
		}
		return parts;
	}
	
	public static class Property {
		public final String propertyName;
		public Property(String propertyName) {
			this.propertyName= propertyName;
		}
	}
	
	

/*
	private final String placeholderPrefix="${";
	private final String valueSeparator=":"; ??? 
	private final String placeholderSuffix="}"; 
	private int findPlaceholderEndIndex(CharSequence buf, int startIndex) {
		int index = startIndex + this.placeholderPrefix.length();
		int withinNestedPlaceholder = 0;
		while (index < buf.length()) {
			if (StringUtils.substringMatch(buf, index, this.placeholderSuffix)) {
				if (withinNestedPlaceholder > 0) {
					withinNestedPlaceholder--;
					index = index + this.placeholderPrefix.length() - 1;
				}
				else {
					return index;
				}
			}
			else if (StringUtils.substringMatch(buf, index, this.placeholderPrefix)) {
				withinNestedPlaceholder++;
				index = index + this.placeholderPrefix.length();
			}
			else {
				index++;
			}
		}
		return -1;
	}

	
	protected String parseStringValue(
				String strVal, PlaceholderResolver placeholderResolver, Set<String> visitedPlaceholders) {
		StringBuilder buf= new StringBuilder();
		int startIndex = strVal.indexOf(this.placeholderPrefix);
		while (startIndex != -1) {
			int endIndex = findPlaceholderEndIndex(buf, startIndex);
			if (endIndex != -1) {
				String placeholder = buf.substring(startIndex + this.placeholderPrefix.length(), endIndex);
				if (!visitedPlaceholders.add(placeholder)) {
					throw new IllegalArgumentException(
							"Circular placeholder reference '" + placeholder + "' in property definitions");
				}
				// Recursive invocation, parsing placeholders contained in the placeholder key.
				placeholder = parseStringValue(placeholder, placeholderResolver, visitedPlaceholders);

				// Now obtain the value for the fully resolved key...
				String propVal = placeholderResolver.resolvePlaceholder(placeholder);
				if (propVal == null && this.valueSeparator != null) {
					int separatorIndex = placeholder.indexOf(this.valueSeparator);
					if (separatorIndex != -1) {
						String actualPlaceholder = placeholder.substring(0, separatorIndex);
						String defaultValue = placeholder.substring(separatorIndex + this.valueSeparator.length());
						propVal = placeholderResolver.resolvePlaceholder(actualPlaceholder);
						if (propVal == null) {
							propVal = defaultValue;
						}
					}
				}
				if (propVal != null) {
					// Recursive invocation, parsing placeholders contained in the
					// previously resolved placeholder value.
					propVal = parseStringValue(propVal, placeholderResolver, visitedPlaceholders);
					buf.replace(startIndex, endIndex + this.placeholderSuffix.length(), propVal);

					
					LOGGER.trace("Resolved placeholder '{}'", placeholder);
					

					startIndex = buf.indexOf(this.placeholderPrefix, startIndex + propVal.length());
				}
				else {
					// Proceed with unprocessed value.
					startIndex = buf.indexOf(this.placeholderPrefix, endIndex + this.placeholderSuffix.length());
				}

				visitedPlaceholders.remove(placeholder);
			}
			else {
				startIndex = -1;
			}
		}
		return null;
	}
	*/
	public Long resolveLong(String name) {
		String replaced= this.placeholderHelper.replacePlaceholders(name, this.properties);
		return Long.valueOf(replaced);
	}

	public void setProperties(Properties properties) {
		this.properties = properties;
	}

	public Properties getProperties() {
		return this.properties;
	}


}
